package io.renren.modules.oatools.utils.http.temp;

import com.alibaba.fastjson.JSON;
import groovy.lang.Binding;
import groovy.lang.GroovyClassLoader;
import groovy.lang.Script;
import io.renren.modules.oatools.utils.http.HttpRequestSend;
import io.renren.modules.oatools.utils.http.OAHttpNetworkInvokeIntercepter;
import okhttp3.*;
import org.apache.logging.log4j.util.Strings;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.Map;

public class LLHttpRequestUtils {
    private final static Logger log = LoggerFactory.getLogger(LLHttpRequestUtils.class);

    private static int serversLoadTimes = 0;
    private static final int maxLoadTimes = 3; // 最大重连次数
    /**
     * @param upResponseBody 上游返回的body
     * @param requestSend    本次请求的参数
     * @return
     * @throws IOException
     */
    public static Map<String, Object> requestSend(String upResponseBody, HttpRequestSend requestSend) throws IOException {
        Boolean isSuccess = true;
        Map<String, Object> reMap = new HashMap<>();
        log.info(JSON.toJSONString(requestSend));
        String requestUrl = null==requestSend.getRequestUrl()?"{}":requestSend.getRequestUrl();
        String requestParams = null==requestSend.getRequestParams()?"{}":requestSend.getRequestParams();
        String paramsGroovy = requestSend.getParamsGroovy();
        String requestHeaders = null==requestSend.getRequestHeaders()?"{}":requestSend.getRequestHeaders();
        String headersGroovy = requestSend.getHeadersGroovy();
        String bodyGroovy = requestSend.getBodyGroovy();
        String requestClientGrooby = requestSend.getRequestClientGrooby();
        String requestBeforeGroovy = requestSend.getRequestBeforeGroovy();
        String requestAfterGroovy = requestSend.getRequestAfterGroovy();
        String reqBody = null==requestSend.getRequestBody()?"{}":requestSend.getRequestBody();
        String requestType = null==requestSend.getRequestType()?"POST":requestSend.getRequestType();
        int isAsyn = null==requestSend.getIsAsyn()?0:Integer.valueOf(requestSend.getIsAsyn().toString());

        /**
         * 通过参数 params 拼接 URL
         */
        Map paramsMap = JSON.parseObject(requestParams, Map.class);
        HttpUrl.Builder urlBuilder = HttpUrl.parse(requestUrl).newBuilder();
        Map returnParamsMap = new HashMap();
        /** 执行Groovy脚本 **/
        if (Strings.isNotEmpty(paramsGroovy)) {
            Object[] executeParamsGroovy = new Object[]{upResponseBody, paramsMap, reqBody};
            Object executeParamsResult = executeGroovy(executeParamsGroovy, paramsGroovy);
            returnParamsMap = (Map) executeParamsResult;
        }
        returnParamsMap.forEach((key, value) -> {
            urlBuilder.addQueryParameter(key.toString(), value.toString()).build();
            log.info(key + "<<<<<<<>>>>>" + value);
        });
        HttpUrl url = urlBuilder.build();

        /**
         * 拼接 请求头
         */
        Headers.Builder headersBuilder = new Headers.Builder();
        Map headersMap = JSON.parseObject(requestHeaders, Map.class);

        /** 执行Groovy脚本 **/
        if (Strings.isNotEmpty(headersGroovy)) {
            Object[] executeHeadersGroovy = new Object[]{upResponseBody, headersMap, reqBody};
            Object executeHeadersResult = executeGroovy(executeHeadersGroovy, headersGroovy);
            headersMap = (Map) executeHeadersResult;
        }
//        if (null != headersMap&& headersMap.size()>0)
        headersMap.forEach((key, value) -> {
            headersBuilder.add(key.toString(), value.toString());
            log.info(key.toString() + "《《《《《《《headers》》》》》》》》" + value.toString());
        });
        Headers headers = headersBuilder.build();
        log.info(headers.toString() + "<<<<<<请求地址》》》》》》》》》" + url);

        /**
         * OkHttpClient
         */

        OkHttpClient.Builder clientBuilder = new OkHttpClient().newBuilder();
        if (Strings.isNotEmpty(requestClientGrooby)) {
            Object[] executeClientGroovy = new Object[]{upResponseBody};
            clientBuilder = (OkHttpClient.Builder) executeGroovy(executeClientGroovy, requestClientGrooby);
        }
        OkHttpClient client = clientBuilder
                .addInterceptor(new OAHttpNetworkInvokeIntercepter(requestSend))//拦截器
                .build();

        /**
         * 拼接 body
         */
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, reqBody);
        /** Body **/
        if (Strings.isNotEmpty(bodyGroovy)) {
            Object[] executeBodyGroovy = new Object[]{upResponseBody, url, reqBody, headers};
            body = (RequestBody) executeGroovy(executeBodyGroovy, bodyGroovy);
        }

        /**
         * 请求执行前
         */
        Request.Builder requestBuilder = new Request.Builder();
        if (Strings.isNotEmpty(requestBeforeGroovy)) {
            Object[] executeBeforeGroovy = new Object[]{upResponseBody, url, body, headers};
            requestBuilder = (Request.Builder) executeGroovy(executeBeforeGroovy, requestBeforeGroovy);
        }
        Request request = requestBuilder.url(url).build();
        if (requestType.equals("POST")) {
            request = requestBuilder.url(url).post(body).headers(headers).build();
        } else if (requestType.equals("GET")) {
            request = requestBuilder.url(url).get().headers(headers).build();
        }
        serversLoadTimes = 0;
        //默认为同步（异步获取不到返回值）
        if (isAsyn > 0) {
            Call call = client.newCall(request);//异步
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    //失败回调
                    log.error("失败回调 onFailure: " + e.getMessage());
                    if (e instanceof SocketTimeoutException && serversLoadTimes < maxLoadTimes) {// 如果超时并未超过指定次数，则重新连接
                        serversLoadTimes++;
                        log.error("重连次数: 【" + serversLoadTimes + "】 ");
                        client.newCall(call.request()).enqueue(this);
                    } else {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    /**
                     * 返回值处理
                     **/
                    if (Strings.isNotEmpty(requestAfterGroovy)) {
                        Object[] executeAfterGroovy = new Object[]{upResponseBody, response};
                        executeGroovy(executeAfterGroovy, requestAfterGroovy);
                    }

                    if (response.isSuccessful()) {
                        if (null != response.body()) {
                            String responseBody = response.body().string();
                            reMap.put("mag",responseBody);
                            log.info("请求后返回数据： " + responseBody);
                        }
                    } else {
                        log.error("token请求接口地址失败：" + url);
                    }
                    // 不论成功与否，记得在处理完响应后关闭响应体以释放资源
                    response.body().close();
                }

            });
        } else {
            Response response = client.newCall(request).execute();//同步
            /**
             * 返回值处理
             **/
            if (Strings.isNotEmpty(requestAfterGroovy)) {
                Object[] executeAfterGroovy = new Object[]{upResponseBody, response};
                executeGroovy(executeAfterGroovy, requestAfterGroovy);
            }

            if (response.isSuccessful()) {
                if (null != response.body()) {
                    String responseBody = response.body().string();
                    reMap.put("mag",responseBody);
                    log.info("请求后返回数据： " + responseBody);
                }
            } else {
                log.error("请求接口地址失败：" + url);
            }
            response.body().close();
            reMap.put("success",isSuccess);
            reMap.put("url",url);
            return reMap;
        }
        return reMap;
    }

    /**
     * 执行Groovy脚本
     *
     * @param objects Groovy接收的参数
     * @param groovy  要执行的脚本
     * @return
     */
    private static Object executeGroovy(Object[] objects, String groovy) {
        if (Strings.isNotEmpty(groovy)) { // 改用Spring/SpringBoot常用的Strings工具
            try (GroovyClassLoader groovyClassLoader = new GroovyClassLoader()) { // 使用try-with-resources自动清理
                Class<?> scriptClass = groovyClassLoader.parseClass(groovy);
                Script script = InvokerHelper.createScript(scriptClass, new Binding());

                log.info("执行脚本: {}", groovy);
                Object executeResult = script.invokeMethod("execute", objects);
                log.info("执行后返回的值：{}", executeResult);

                return executeResult;
            } catch (Exception e) {
                log.error("Groovy脚本执行失败", e);
                throw new RuntimeException("脚本执行异常: " + e.getMessage(), e);
            }
        }
        return null;
    }

    public static void main(String[] args) throws IOException {
        // 准备请求体
        Map<String, Object> body = new HashMap<>();
//        body.put("violationID", violationID);
//
//        log.info("请求体内容：" + JSONUtil.toJSONString(body));

        // 发送HTTP请求
//        HttpRequestSend httpRequestSend = new HttpRequestSend();
//        httpRequestSend.setRequestUrl("http://10.130.160.152:7512/api/Violation/ViolationInfoRegister");
//        httpRequestSend.setRequestType("POST");
//
//        // 发送请求并处理响应
//        Map<String, Object> response = OAHttpRequestUtils.requestSend(JSON.toJSONString(body), httpRequestSend);
//
//

        HttpRequestSend httpRequestSend = new HttpRequestSend();
        httpRequestSend.setRequestUrl("");
//        httpRequestSend.setRequestBody(null);
//        httpRequestSend.setRequestParams("{}");
        httpRequestSend.setRequestType("GET");
//        httpRequestSend.setRequestHeaders("{}");
//        httpRequestSend.setRequestBody("{}");
//        httpRequestSend.setIsAsyn(0);
//        httpRequestSend.setParamsGroovy("");
        try {
            System.out.println(requestSend(null,httpRequestSend));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}